﻿using Checc_CircularCulvert_Assemble.commons;
using Checc_CircularCulvert_Assemble.commons.overall;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Bentley.CIMNET.CIMGeometry.Solid.SolidUtil.Modify;
using GeneralHelpers = CheccCoverplateCulvertAssemble.Tools.GeneralBank;

namespace Checc_CircularCulvert_Assemble.structures
{
    /// <summary>
    /// 出口急流槽
    /// </summary>
    public class ChuteOutStructure
    {
        public List<Element> Elements { get; set; } = new List<Element>();
        public void CreateChuteOutStructure(CommonChuteOut commonChuteOut, double angle, double culvertOpeningWidth, DgnModel dgnModel)
        {
            CreateAqueductBody(
                commonChuteOut.Height * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.EndlongSlopeRatio,
                commonChuteOut.Deep * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.DeflectionAngle,
                commonChuteOut.BottomPaveThickness * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.WallThickness * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.SideWidth * 0.01 * GeneralHelpers.UorToMeters,
               culvertOpeningWidth,
                dgnModel
                );

            CreatePave(
                commonChuteOut.Height * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.EndlongSlopeRatio,
                commonChuteOut.Deep * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.DeflectionAngle,
                commonChuteOut.BottomPaveThickness * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.WallThickness * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.SideWidth * 0.01 * GeneralHelpers.UorToMeters,

                commonChuteOut.WingWallLength * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.WingWallAngleFlare,
                commonChuteOut.CutoffWallHeight * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.CutoffWallWidth * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.EarWallWidth * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.EarWallHeight * 0.01 * GeneralHelpers.UorToMeters,
                commonChuteOut.EarWallInterval * 0.01 * GeneralHelpers.UorToMeters,
                culvertOpeningWidth,
                dgnModel
                );
        }

        /// <summary>
        /// 创建槽体
        /// </summary>
        /// <param name="height">槽体高度</param>
        /// <param name="slopeRatio">槽体纵坡比</param>
        /// <param name="deep">槽深</param>
        /// <param name="angle">偏转角</param>
        /// <param name="paveThickness">槽底铺砌厚度</param>
        /// <param name="wallThickness">槽壁厚度</param>
        /// <param name="addWidth">洞口侧加宽</param>
        /// <param name="culvertOpeningWidth">涵洞口宽度</param>
        private void CreateAqueductBody(double height, double slopeRatio, double deep, double angle, double paveThickness, double wallThickness, double addWidth, double culvertOpeningWidth, DgnModel dgnModel)
        {
            double exceedLength = 0;//超出长度
            DPoint3d startDp = DPoint3d.Zero;
            DPoint3d endDp = new(height * slopeRatio, 0, -height);
            double length = startDp.Distance(endDp);
            DVector3d.TryNormalizeToTarget(startDp, endDp, out DVector3d unitVector);
            //底面
            List<DPoint3d> dPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,0)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,deep)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness,deep)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness,-paveThickness)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness),-paveThickness)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness),deep)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5),deep)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5),0)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,0)+length*unitVector
            };
            ShapeElement shape = new ShapeElement(dgnModel, null, dPoint3Ds.ToArray());
            //shape.AddToModel();
            //截面拉伸
            LineElement lineElementBottom = new LineElement(dgnModel, null, new DSegment3d(new(), DPoint3d.Zero + 2 * length * -unitVector));
            //lineElementBottom.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entity, shape.GetCurveVector(), lineElementBottom.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOut, entity, null, dgnModel);
            //ehOut.AddToModel();

            #region 角度裁剪
            double Degrees = angle * -1;

            DVector3d resultDvec = DVector3d.UnitY.RotateXY(Angle.FromDegrees(Degrees));

            LineElement lineElementAngle = new LineElement(GeneralHelpers.Default3DModel, null, new DSegment3d(DPoint3d.Zero - resultDvec * 10 * GeneralHelpers.UorToMeters, DPoint3d.Zero + resultDvec * 10 * GeneralHelpers.UorToMeters));
            //lineElementAngle.AddToModel();

            BCIMNETGS.SolidUtil.Modify.CutSolidsWithCurves(out SolidKernelEntity[] solidKernels, entity, lineElementAngle.GetCurveVector(), SolidCutMethod.Split, SolidCutDirection.Both, SolidCutMode.Through, 0);
            entity = solidKernels[0];

            #endregion

            #region 槽体底部延伸

            //底面
            List<DPoint3d> extendDPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness,0)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness,-paveThickness)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness),-paveThickness)+length*unitVector,
                new DPoint3d(exceedLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness),0)+length*unitVector,
                new DPoint3d(exceedLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+wallThickness,0)+length*unitVector
            };
            ShapeElement shapeExtend = new ShapeElement(dgnModel, null, extendDPoint3Ds.ToArray());
            //shapeExtend.AddToModel();
            //截面拉伸
            LineElement lineElementExtend = new LineElement(dgnModel, null, new DSegment3d(new(), DPoint3d.Zero + paveThickness * slopeRatio * -DVector3d.UnitX));
            //lineElementExtend.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entityExtend, shapeExtend.GetCurveVector(), lineElementExtend.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOutExtend, entityExtend, null, dgnModel);
            //ehOutExtend.AddToModel();
            this.Elements.Add(ehOutExtend);

            #region 裁剪体

            SolidKernelEntity[] solidKernelEntities = new SolidKernelEntity[] { entityExtend };
            BentleyStatus status = Modify.BooleanSubtract(ref entity, ref solidKernelEntities, solidKernelEntities.Length);

            Convert1.BodyToElement(out Element ehOutAqueduct, entity, null, dgnModel);
            //ehOutAqueduct.AddToModel();
            this.Elements.Add(ehOutAqueduct);
            #endregion

            #endregion
        }

        /// <summary>
        /// 创建铺砌
        /// </summary>
        /// <param name="height">槽体高度</param>
        /// <param name="slopeRatio">槽体纵坡比</param>
        /// <param name="deep">槽深</param>
        /// <param name="angle">偏转角</param>
        /// <param name="paveThickness">槽底铺砌厚度</param>
        /// <param name="wallThickness">槽壁厚度</param>
        /// <param name="addWidth">洞口侧加宽</param>
        /// <param name="wingWallLength">翼墙长度</param>
        /// <param name="wingWallAngle">翼墙扩散角</param>
        /// <param name="cutoffWallHeight">截水墙高度</param>
        /// <param name="cutoffWallWidth">截水墙宽度</param>
        /// <param name="earWallWidth">耳墙宽度</param>
        /// <param name="earWallHeight">耳墙高度</param>
        /// <param name="earWallInterval">耳墙间距</param>
        /// <param name="culvertOpeningWidth">涵洞口宽度</param>
        /// <param name="dgnModel"></param>
        private void CreatePave(double height, double slopeRatio, double deep, double angle, double paveThickness, double wallThickness, double addWidth,
            double wingWallLength, double wingWallAngle, double cutoffWallHeight, double cutoffWallWidth, double earWallWidth, double earWallHeight, double earWallInterval, double culvertOpeningWidth, DgnModel dgnModel
            )
        {
            DPoint3d startDp = DPoint3d.Zero;
            DPoint3d endDp = new(height * slopeRatio, 0, -height);
            double length = startDp.Distance(endDp);
            DVector3d.TryNormalizeToTarget(startDp, endDp, out DVector3d unitVector);

            //扩散角渐变长度
            double gradualChangeLen = wallThickness * 1 / Math.Cos(Math.PI * wingWallAngle / 180.0);
            //扩散角偏移宽度
            double skewingWidth = wingWallLength * Math.Tan(Math.PI * wingWallAngle / 180.0);
            #region 右侧墙
            //底面
            List<DPoint3d> rightDPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,0)+length*unitVector,
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,deep)+length*unitVector,
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen,deep)+length*unitVector,
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen,0)+length*unitVector,
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5,0)+length*unitVector
            };
            ShapeElement shapeRight = new ShapeElement(dgnModel, null, rightDPoint3Ds.ToArray());
            //shapeRight.AddToModel();
            //截面拉伸
            LineElement lineElementRight = new LineElement(dgnModel, null, new DSegment3d(new(), new(wingWallLength, skewingWidth)));
            //lineElementRight.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entityRight, shapeRight.GetCurveVector(), lineElementRight.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOutRight, entityRight, null, dgnModel);
            //ehOutRight.AddToModel();
            this.Elements.Add(ehOutRight);
            #endregion

            #region 左侧墙
            //底面
            List<DPoint3d> leftDPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen),0)+length*unitVector,
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen),deep)+length*unitVector,
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5),deep)+length*unitVector,
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5),0)+length*unitVector,
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen),0)+length*unitVector
            };
            ShapeElement shapeLeft = new ShapeElement(dgnModel, null, leftDPoint3Ds.ToArray());
            //shapeLeft.AddToModel();
            //截面拉伸
            LineElement lineElementLeft = new LineElement(dgnModel, null, new DSegment3d(new(), new(wingWallLength, -skewingWidth)));
            //lineElementLeft.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entityLeft, shapeLeft.GetCurveVector(), lineElementLeft.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOutLeft, entityLeft, null, dgnModel);
            //ehOutLeft.AddToModel();
            this.Elements.Add(ehOutLeft);
            #endregion

            #region 铺砌
            List<DPoint3d> paveDPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen,0)+length*unitVector,
                new DPoint3d(0,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen),0)+length*unitVector,
                new DPoint3d(wingWallLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen)-skewingWidth,0)+length*unitVector,
                new DPoint3d(wingWallLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen+skewingWidth,0)+length*unitVector,


                new DPoint3d(0,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen,0)+length*unitVector,
            };
            ShapeElement shapePave = new ShapeElement(dgnModel, null, paveDPoint3Ds.ToArray());
            //shapePave.AddToModel();
            //截面拉伸
            LineElement lineElementPave = new LineElement(dgnModel, null, new DSegment3d(new(), new(0, 0, -paveThickness)));
            //lineElementPave.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entityPave, shapePave.GetCurveVector(), lineElementPave.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOutPave, entityPave, null, dgnModel);
            //ehOutPave.AddToModel();
            this.Elements.Add(ehOutPave);
            #endregion

            #region 截水墙
            List<DPoint3d> cutoffWallDPoint3Ds = new List<DPoint3d>()
            {
                new DPoint3d(wingWallLength-cutoffWallWidth,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen+(wingWallLength-cutoffWallWidth) * Math.Tan(Math.PI * wingWallAngle / 180.0),-paveThickness)+length*unitVector,
                new DPoint3d(wingWallLength-cutoffWallWidth,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen)-(wingWallLength-cutoffWallWidth) * Math.Tan(Math.PI * wingWallAngle / 180.0),-paveThickness)+length*unitVector,
                new DPoint3d(wingWallLength,-(culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen)-skewingWidth,-paveThickness)+length*unitVector,
                new DPoint3d(wingWallLength,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen+skewingWidth,-paveThickness)+length*unitVector,

                new DPoint3d(wingWallLength-cutoffWallWidth,culvertOpeningWidth* GeneralHelpers.UorToMeters*0.5+gradualChangeLen+(wingWallLength-cutoffWallWidth) * Math.Tan(Math.PI * wingWallAngle / 180.0),-paveThickness)+length*unitVector
            };
            ShapeElement shapeCutoffWall = new ShapeElement(dgnModel, null, cutoffWallDPoint3Ds.ToArray());
            //shapeCutoffWall.AddToModel();
            //截面拉伸
            LineElement lineElementCutoffWall = new LineElement(dgnModel, null, new DSegment3d(new(), new(0, 0, -cutoffWallHeight)));
            //lineElementCutoffWall.AddToModel();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entityCutoffWall, shapeCutoffWall.GetCurveVector(), lineElementCutoffWall.GetCurveVector(), dgnModel, false, true, false, null, null, null, null);
            Convert1.BodyToElement(out Element ehOutCutoffWall, entityCutoffWall, null, dgnModel);
            //ehOutCutoffWall.AddToModel();
            this.Elements.Add(ehOutCutoffWall);
            #endregion
        }


    }
}
